package com.leetcode;


import java.util.ArrayDeque;
import java.util.Deque;

/**
 * 1124. 表现良好的最长时间段 (中等)
 * <p>
 * 给你一份工作时间表 hours，上面记录着某一位员工每天的工作小时数。
 * 我们认为当员工一天中的工作小时数大于 8 小时的时候，那么这一天就是「劳累的一天」。
 * 所谓「表现良好的时间段」，意味在这段时间内，「劳累的天数」是严格 大于「不劳累的天数」。
 * 请你返回「表现良好时间段」的最大长度。
 */
public class LeetCode1124 {

    public static void main(String[] arg0) {
        int[] hours = new int[]{6, 9, 9, 9};
        System.out.println("「表现良好时间段」的最大长度 = " + longestWPI(hours));
    }

    /**
     * 题解的正确做法 -- 贪心
     */
    public static int longestWPI(int[] hours) {
        int n = hours.length;
        int[] s = new int[n + 1];
        Deque<Integer> stk = new ArrayDeque<>();
        stk.push(0);
        for (int i = 1; i <= n; i++) {
            s[i] = s[i - 1] + (hours[i - 1] > 8 ? 1 : -1);
            if (s[stk.peek()] > s[i]) { // stk队列记录的好像都是s[i]小于0的下标，并且s[i]必须越来越小才能放入队列
                System.out.println( "stk.peek() = " + stk.peek() + ", s[stk.peek()] = " + s[stk.peek()]);
                System.out.println("i = " + i + ", s[i] = " + s[i]);
                stk.push(i);
            }
        }

        int res = 0;
        for (int r = n; r >= 1; r--) {
            while (!stk.isEmpty() && s[stk.peek()] < s[r]) {
                res = Math.max(res, r - stk.pop());
            }
        }
        return res;
    }


    /**
     * 自己写的错误的解法，{9， 6， 9} 这种返回 3 的用这个方法只能返回 1
     */
    public static int longestWPI(int[] hours, String error) {
        // 此题一次循环即可，也没有必要用滑动窗口、动态规划等。
        int res = 0;

        int startMax = 0;
        int startIndex = 0;
        int defen = -1;
        boolean isStart = true;
        boolean isFirst = false;
        for (int i = 0; i < hours.length; i++) {
            if (hours[i] > 8) {
                defen++;
                if (isFirst) startMax++;
            } else {
                defen--;
                if (isFirst) isFirst = false;
                if (defen == -1) {
                    res = Math.max(res, i - startIndex);
                    isStart = true;
                }
                if (defen < -1) {
                    defen = -1;
                }
            }
            if (defen == 0 && isStart) {
                startIndex = i;
                isStart = false;
                startMax = 1;
                isFirst = true;
            }
            if (i == hours.length - 1 && defen >= 0) {
                int lastRes = i - startIndex + Math.min(startMax, startIndex + 1);
                res = Math.max(res, lastRes);
            }
        }

        return res;
    }

}
